package com.zenithmind.document.pojo.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zenithmind.common.base.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

import jakarta.validation.constraints.*;

/**
 * 文档分类聚合根
 * 遵循单一职责原则：专注于分类层级管理
 * 遵循封装原则：通过方法控制层级关系
 * 遵循开闭原则：支持动态层级扩展
 *
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@EqualsAndHashCode(callSuper = true)
@Getter
@NoArgsConstructor
@TableName("document_category")
@Schema(description = "文档分类聚合根")
public class DocumentCategory extends BaseEntity {

    /**
     * 分类状态枚举
     */
    public enum CategoryStatus {
        DISABLED(0, "禁用"),
        ENABLED(1, "启用");

        private final int code;
        private final String description;

        CategoryStatus(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static CategoryStatus fromCode(int code) {
            for (CategoryStatus status : values()) {
                if (status.code == code) {
                    return status;
                }
            }
            throw new IllegalArgumentException("未知的分类状态代码: " + code);
        }
    }

    /**
     * 最大层级深度
     */
    public static final int MAX_LEVEL = 5;

    /**
     * 分类名称
     */
    @NotBlank(message = "分类名称不能为空")
    @Size(max = 100, message = "分类名称长度不能超过100个字符")
    @TableField("name")
    @Schema(description = "分类名称")
    private String name;

    /**
     * 分类描述
     */
    @Size(max = 500, message = "分类描述长度不能超过500个字符")
    @TableField("description")
    @Schema(description = "分类描述")
    private String description;

    /**
     * 父分类ID
     */
    @TableField("parent_id")
    @Schema(description = "父分类ID")
    private String parentId;

    /**
     * 分类层级
     */
    @Min(value = 1, message = "分类层级不能小于1")
    @Max(value = MAX_LEVEL, message = "分类层级不能超过" + MAX_LEVEL)
    @TableField("level")
    @Schema(description = "分类层级")
    private Integer level;

    /**
     * 分类路径
     */
    @TableField("path")
    @Schema(description = "分类路径")
    private String path;

    /**
     * 图标URL
     */
    @TableField("icon_url")
    @Schema(description = "图标URL")
    private String iconUrl;

    /**
     * 排序值
     */
    @Min(value = 0, message = "排序值不能为负数")
    @TableField("sort_order")
    @Schema(description = "排序值")
    private Integer sortOrder = 0;

    /**
     * 状态
     */
    @NotNull(message = "分类状态不能为空")
    @TableField("status")
    @Schema(description = "分类状态")
    private Integer status;

    /**
     * 文档数量
     */
    @Min(value = 0, message = "文档数量不能为负数")
    @TableField("document_count")
    @Schema(description = "文档数量")
    private Long documentCount = 0L;

    /**
     * 创建者ID
     */
    @NotBlank(message = "创建者ID不能为空")
    @TableField("creator_id")
    @Schema(description = "创建者ID")
    private String creatorId;

    // ========== 业务方法 ==========

    /**
     * 创建根分类
     */
    public static DocumentCategory createRoot(String name, String description, String creatorId) {
        DocumentCategory category = new DocumentCategory();
        category.setName(name);
        category.setDescription(description);
        category.setCreatorId(creatorId);
        category.setLevel(1);
        category.setStatus(CategoryStatus.ENABLED.getCode());
        category.setSortOrder(0);
        return category;
    }

    /**
     * 创建子分类
     */
    public static DocumentCategory createChild(String name, String description,
                                             DocumentCategory parent, String creatorId) {
        if (parent == null) {
            throw new IllegalArgumentException("父分类不能为空");
        }
        if (parent.getLevel() >= MAX_LEVEL) {
            throw new IllegalArgumentException("分类层级不能超过" + MAX_LEVEL + "级");
        }

        DocumentCategory category = new DocumentCategory();
        category.setName(name);
        category.setDescription(description);
        category.setParentId(parent.getId());
        category.setCreatorId(creatorId);
        category.setLevel(parent.getLevel() + 1);
        category.setStatus(CategoryStatus.ENABLED.getCode());
        category.setSortOrder(0);
        return category;
    }

    /**
     * 设置分类名称（带验证）
     */
    public void setName(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("分类名称不能为空");
        }
        if (name.length() > 100) {
            throw new IllegalArgumentException("分类名称长度不能超过100个字符");
        }
        this.name = name.trim();
    }

    /**
     * 设置分类描述（带验证）
     */
    public void setDescription(String description) {
        if (description != null && description.length() > 500) {
            throw new IllegalArgumentException("分类描述长度不能超过500个字符");
        }
        this.description = description;
    }

    /**
     * 设置创建者ID
     */
    public void setCreatorId(String creatorId) {
        if (creatorId == null || creatorId.trim().isEmpty()) {
            throw new IllegalArgumentException("创建者ID不能为空");
        }
        this.creatorId = creatorId;
    }

    /**
     * 设置分类层级
     */
    public void setLevel(Integer level) {
        if (level == null || level < 1 || level > MAX_LEVEL) {
            throw new IllegalArgumentException("分类层级必须在1-" + MAX_LEVEL + "之间");
        }
        this.level = level;
    }

    /**
     * 设置分类路径
     */
    public void setPath(String path) {
        this.path = path;
    }

    /**
     * 设置父分类ID
     */
    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    /**
     * 设置排序值
     */
    public void setSortOrder(Integer sortOrder) {
        if (sortOrder != null && sortOrder < 0) {
            throw new IllegalArgumentException("排序值不能为负数");
        }
        this.sortOrder = sortOrder != null ? sortOrder : 0;
    }

    /**
     * 设置状态
     */
    public void setStatus(Integer status) {
        if (status == null) {
            throw new IllegalArgumentException("分类状态不能为空");
        }
        // 验证状态值是否有效
        CategoryStatus.fromCode(status);
        this.status = status;
    }

    /**
     * 设置文档数量
     */
    public void setDocumentCount(Long documentCount) {
        if (documentCount != null && documentCount < 0) {
            throw new IllegalArgumentException("文档数量不能为负数");
        }
        this.documentCount = documentCount != null ? documentCount : 0L;
    }

    /**
     * 获取分类状态枚举
     */
    public CategoryStatus getCategoryStatus() {
        return status != null ? CategoryStatus.fromCode(status) : null;
    }

    /**
     * 检查是否为根分类
     */
    public boolean isRoot() {
        return parentId == null || parentId.trim().isEmpty();
    }

    /**
     * 检查是否为叶子分类
     */
    public boolean isLeaf() {
        return level != null && level.equals(MAX_LEVEL);
    }

    /**
     * 检查是否启用
     */
    public boolean isEnabled() {
        return CategoryStatus.ENABLED.getCode() == (status != null ? status : -1);
    }

    /**
     * 启用分类
     */
    public void enable() {
        this.status = CategoryStatus.ENABLED.getCode();
    }

    /**
     * 禁用分类
     */
    public void disable() {
        this.status = CategoryStatus.DISABLED.getCode();
    }

    /**
     * 增加文档数量
     */
    public void incrementDocumentCount() {
        this.documentCount++;
    }

    /**
     * 减少文档数量
     */
    public void decrementDocumentCount() {
        if (this.documentCount > 0) {
            this.documentCount--;
        }
    }

    /**
     * 生成分类路径
     */
    public void generatePath() {
        if (isRoot()) {
            this.path = "/" + this.getId();
        } else {
            // 路径应该由服务层根据父分类路径生成
            this.path = null;
        }
    }

    /**
     * 检查是否可以删除
     */
    public boolean canDelete() {
        return this.documentCount == 0;
    }

    /**
     * 检查分类信息是否完整
     */
    public boolean isComplete() {
        return name != null && !name.trim().isEmpty() &&
               creatorId != null && !creatorId.trim().isEmpty() &&
               level != null && level > 0 && level <= MAX_LEVEL &&
               status != null;
    }

    /**
     * 获取层级缩进字符串（用于显示）
     */
    public String getLevelIndent() {
        if (level == null || level <= 1) {
            return "";
        }
        return "  ".repeat(level - 1);
    }
}
